//
//  ChangePtr.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/6/25.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef ChangePtr_hpp
#define ChangePtr_hpp

#include <stdio.h>
#include <iostream>

//改变指针所有权（std :: auto_ptr就是这儿做的，但这样有很多的问题）
template <class T>
class AutoPtr2 {
    T *m_ptr;
    
public:
    AutoPtr2(T *ptr = nullptr):m_ptr(ptr){
        
    }
    
    ~AutoPtr2(){
        delete m_ptr;
    }
//    复制构造函数
    AutoPtr2(const AutoPtr2 &at){
        
        m_ptr = at.m_ptr;
        at.m_ptr = nullptr;
    }
    //转移指针所有权
    AutoPtr2 &operator=(AutoPtr2 &a){
        if (&a == this) {
            return *this;
        }
        
        delete m_ptr;
        m_ptr = a.m_ptr;
        a.m_ptr = nullptr;
        return *this;
    }
    
    T& operator*() const { return *m_ptr; }
    T* operator->() const { return m_ptr; }
    bool isNull() const { return m_ptr == nullptr;  }
    
    
    
    
    
    
};

class Resource2
{
public:
    Resource2() { std::cout << "Resource acquired\n"; }
    ~Resource2() { std::cout << "Resource destroyed\n"; }
};



/*
 AutoPtr2<Resource2> ap1(new Resource2);
 
 AutoPtr2<Resource2> ap2;
 
 std::cout << "res1 is " << (ap1.isNull() ? "null\n" : "not null\n");
 std::cout << "res2 is " << (ap2.isNull() ? "null\n" : "not null\n");
 
 ap2 = ap1;
 
 std::cout << "res1 is " << (ap1.isNull() ? "null\n" : "not null\n");
 std::cout << "res2 is " << (ap2.isNull() ? "null\n" : "not null\n");
 */

/*
 
 现在将是讨论std :: auto_ptr的适当时机。在C ++ 98中引入的std :: auto_ptr是C ++在标准智能指针上的第一次尝试。 std :: auto_ptr选择像Auto_ptr2类那样实现移动语义。

 首先，因为std :: auto_ptr通过复制构造函数和赋值运算符实现了移动语义，所以通过值将std :: auto_ptr传递给一个函数将导致您的资源移动到函数参数中（并在函数结尾被销毁当功能参数超出范围时）。然后，当你从调用者访问你的auto_ptr参数时（没有意识到它被传输和删除），你突然解除引用一个空指针。崩溃！
 
 其次，std :: auto_ptr总是使用非数组删除来删除其内容。这意味着auto_ptr在动态分配的数组中无法正常工作，因为它使用了错误的解除分配。更糟糕的是，它不会阻止你将它传递给一个动态数组，这将导致管理不善，导致内存泄漏。
 
 规则：std :: auto_ptr已弃用，不应使用。
 */


#endif /* ChangePtr_hpp */
